package com.example.easytts.service

import com.example.easytts.model.IpUsage
import com.example.easytts.model.Language
import com.example.easytts.repository.IpUsageRepository
import com.example.easytts.model.User
import com.example.easytts.repository.UserRepository
import com.example.easytts.service.OptionsService
import org.springframework.beans.factory.annotation.Value
import org.springframework.stereotype.Service
import org.springframework.transaction.annotation.Transactional
import java.time.LocalDate
import com.example.easytts.model.TtsRecord
import com.example.easytts.repository.TtsRecordRepository
import java.time.LocalDateTime

class MemberDailyLimitExceededException(val limit: Int) : RuntimeException(
    "会员您好，您今日会员专属免费字数（$limit）已用完，如需继续使用请明日再来或充值积分。"
)

class IpDailyLimitExceededException(val limit: Int) : RuntimeException(
    "访客您好，由于本站访问量激增，微软提供的每月50万字免费额度已无法满足当前网站使用量，不得已从即日起开启每日免费字数限制功能，您今日免费字数（$limit）已满额，如需生成更多字数，请联系客服。"
)

@Service
class TtsService(
    private val azureTtsService: AzureTtsService,
    private val ipUsageRepository: IpUsageRepository,
    private val userRepository: UserRepository,
    private val optionsService: OptionsService,
    private val ttsRecordRepository: TtsRecordRepository,
    @Value("\${tts.daily-limit:100}")
    private val dailyLimit: Int
) {
    private val MEMBER_DAILY_LIMIT = 100_000
    private val IP_DAILY_LIMIT = 1_000

    @Transactional
    fun synthesizeSpeech(text: String, voice : String, language: String, userId: Long?): String {
        val truncatedText = if (text.length > 10000) text.substring(0, 10000) else text
        var username: String? = null
        var userIdToSave: Long? = null
        var ipToSave: String? = null
        var cosUrl: String
        if (userId != null) {
            val user = userRepository.findById(userId).orElseThrow { Exception("用户不存在") }
            username = user.username
            userIdToSave = user.id
            val today = LocalDate.now()
            var updatedUser = user
            // 会员逻辑（积分>0）
            if (user.points > 0) {
                if (user.lastUsedDate != today) {
                    updatedUser = user.copy(
                        points = user.points - 1,
                        todayUsedChars = 0,
                        lastUsedDate = today
                    )
                }
                if (updatedUser.todayUsedChars + truncatedText.length > MEMBER_DAILY_LIMIT) {
                    throw MemberDailyLimitExceededException(MEMBER_DAILY_LIMIT)
                }
                cosUrl = azureTtsService.synthesizeSpeech(truncatedText, voice, language, true, true)
                updatedUser = updatedUser.copy(todayUsedChars = updatedUser.todayUsedChars + truncatedText.length)
                userRepository.save(updatedUser)
                // 获取IP
                var ip = ThreadLocalIpHolder.get()
                if (ip == null) {
                    val request = org.springframework.web.context.request.RequestContextHolder.getRequestAttributes()
                    if (request is org.springframework.web.context.request.ServletRequestAttributes) {
                        ip = request.request.getHeader("X-Forwarded-For")?.split(",")?.get(0)
                            ?: request.request.remoteAddr
                        ThreadLocalIpHolder.set(ip)
                    }
                }
                ipToSave = ThreadLocalIpHolder.get() ?: ""
                // 保存记录
                ttsRecordRepository.save(TtsRecord(
                    userId = userIdToSave,
                    username = username,
                    ip = ipToSave,
                    voice = voice,
                    text = truncatedText,
                    cosUrl = cosUrl,
                    createdAt = LocalDateTime.now()
                ))
                return cosUrl
            }
            // 非会员/会员到期，走访客逻辑（和未登录一致，继续往下走）
        }
        // 访客逻辑，按IP限制（未登录或会员到期）
        var ip = ThreadLocalIpHolder.get()
        if (ip == null) {
            // 兜底：尝试从RequestContextHolder获取HttpServletRequest
            val request = org.springframework.web.context.request.RequestContextHolder.getRequestAttributes()
            if (request is org.springframework.web.context.request.ServletRequestAttributes) {
                ip = request.request.getHeader("X-Forwarded-For")?.split(",")?.get(0)
                    ?: request.request.remoteAddr
                ThreadLocalIpHolder.set(ip)
            }
        }
        val finalIp = ThreadLocalIpHolder.get() ?: throw Exception("无法获取IP")
        ipToSave = finalIp
        val currentDayStr = LocalDate.now().toString()
        val usages = ipUsageRepository.findByIpAndUsageDay(finalIp, currentDayStr)
        val usage = if (usages.isEmpty()) {
            IpUsage(ip = finalIp, usageDayStr = currentDayStr)
        } else {
            // 如果有多条记录，合并字符数并保留第一条
            val totalChars = usages.sumOf { it.characterCount }
            val firstUsage = usages.first()
            firstUsage.characterCount = totalChars
            // 删除其他重复记录
            if (usages.size > 1) {
                ipUsageRepository.deleteAll(usages.drop(1))
            }
            firstUsage
        }
        if (usage.characterCount + truncatedText.length > IP_DAILY_LIMIT) {
            throw IpDailyLimitExceededException(IP_DAILY_LIMIT)
        }
        cosUrl = azureTtsService.synthesizeSpeech(truncatedText, voice, language, true, false)
        usage.characterCount += truncatedText.length
        ipUsageRepository.save(usage)
        // 保存记录
        ttsRecordRepository.save(TtsRecord(
            userId = userIdToSave,
            username = username,
            ip = ipToSave,
            voice = voice,
            text = truncatedText,
            cosUrl = cosUrl,
            createdAt = LocalDateTime.now()
        ))
        return cosUrl
    }
    
    fun getRemainingCharacters(ip: String): Int {
        val currentDayStr = LocalDate.now().toString()
        val usages = ipUsageRepository.findByIpAndUsageDay(ip, currentDayStr)
        val totalChars = usages.sumOf { it.characterCount }
        return dailyLimit - totalChars
    }

    fun getIpTotalCharacters(ip: String): Int {
        return ipUsageRepository.sumCharacterCountByIp(ip) ?: 0
    }

    fun getAllTotalCharacters(): Int {
        return ipUsageRepository.sumAllCharacterCount() ?: 0
    }
} 